package com.xu.cloud.auth.service.impl;

import com.xu.cloud.auth.component.PasswordComponent;
import com.xu.cloud.auth.component.TokenComponent;
import com.xu.cloud.auth.component.UserInfoComponent;
import com.xu.cloud.auth.exception.AuthErrorCodeEnum;
import com.xu.cloud.auth.pojo.domain.UserInfoDO;
import com.xu.cloud.auth.pojo.http.LoginResp;
import com.xu.cloud.auth.pojo.http.MessageCodeLoginReq;
import com.xu.cloud.auth.pojo.http.PasswordLoginReq;
import com.xu.cloud.auth.pojo.http.ThirdPartyLoginReq;
import com.xu.cloud.auth.service.LoginService;
import com.xu.cloud.auth.service.OAuth2Service;
import com.xu.cloud.common.auth.AuthContext;
import com.xu.cloud.common.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * login service implement
 *
 * @author xuguan
 * @since 2025/2/23
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private OAuth2Service oAuth2Service;
    @Autowired
    private UserInfoComponent userInfoComponent;
    @Autowired
    private PasswordComponent passwordComponent;
    @Autowired
    private TokenComponent tokenComponent;

    @Override
    public LoginResp passwordLogin(PasswordLoginReq req) {
        log.info("密码登录开始, req={}", req);
        AssertUtil.assertNotNull(req);
        final String loginName = req.getLoginName();
        final String password = req.getPassword();
        AssertUtil.assertHasText(loginName);
        AssertUtil.assertHasText(password);

        // 查询客户信息
        final UserInfoDO userInfoDo = userInfoComponent.queryUserInfoByLoginName(loginName);
        AssertUtil.assertNotNull(userInfoDo, AuthErrorCodeEnum.LOGIN_NAME_OR_PASSWORD_ERROR.info().newException());

        // 校验登录密码
        final Long userId = userInfoDo.getId();
        final boolean checkPasswordResult = passwordComponent.checkPassword(userId, password);
        AssertUtil.assertTrue(checkPasswordResult, AuthErrorCodeEnum.LOGIN_NAME_OR_PASSWORD_ERROR.info().newException());

        final LoginResp loginResp = assembleLoginResp(userId);

        log.info("密码登录成功, loginResp={}", loginResp);
        return loginResp;
    }

    @Override
    public LoginResp tokenLogin(String accessToken) {
        log.info("token登录开始, accessToken={}", accessToken);
        // 解析token
        AuthContext authContext = tokenComponent.resolveAccessToken(accessToken, true);

        final Long userId = authContext.getUserId();
        final LoginResp loginResp = assembleLoginResp(userId);

        log.info("token登录成功, loginResp={}", loginResp);
        return loginResp;
    }

    @Override
    public LoginResp messageCodeLogin(MessageCodeLoginReq req) {
        log.info("短信验证码登录开始, req={}", req);
        final String messageToken = req.getMessageToken();
        final String mobileNo = req.getMobileNo();

        // 检验短信验证token
        tokenComponent.checkMessageCodeToken(messageToken, mobileNo);

        // 查询客户信息
        final UserInfoDO userInfoDo = userInfoComponent.queryUserInfoByMobileNo(mobileNo);
        AssertUtil.assertNotNull(userInfoDo, AuthErrorCodeEnum.USER_INFO_NOT_EXIST.info().newException());

        final LoginResp loginResp = assembleLoginResp(userInfoDo.getId());
        log.info("短信验证码登录成功, loginResp={}", loginResp);
        return loginResp;
    }

    @Override
    public LoginResp thirdPartyLogin(ThirdPartyLoginReq req) {
        log.info("第三方登录开始, req={}", req);
        final String thirdPartyType = req.getThirdPartyType();
        final String code = req.getCode();

        // 通过第三方授权用户信息查询系统用户信息
        final UserInfoDO userInfoDo = oAuth2Service.queryUserInfoByOauth2(thirdPartyType, code);
        AssertUtil.assertNotNull(userInfoDo, AuthErrorCodeEnum.USER_INFO_NOT_EXIST.info().newException());

        final LoginResp loginResp = assembleLoginResp(userInfoDo.getId());
        log.info("第三方登录成功, loginResp={}", loginResp);
        return loginResp;
    }

    /**
     * 组装登录响应
     */
    private LoginResp assembleLoginResp(Long userId) {
        // 查询用户信息
        final UserInfoDO userInfoDo = userInfoComponent.queryUserInfoByUserId(userId);
        AssertUtil.assertNotNull(userInfoDo, AuthErrorCodeEnum.USER_INFO_NOT_EXIST.info().newException());

        // 查询用户角色权限信息
        final AuthContext authContext = userInfoComponent.queryAuthContext(userId);

        // 生成登录access_token
        final String accessToken = tokenComponent.createAccessToken(authContext);

        // 组装登录响应
        return LoginResp.builder()
                .userId(userId)
                .mobileNo(userInfoDo.getMobileNo())
                .email(userInfoDo.getEmail())
                .userName(userInfoDo.getUsername())
                .sex(userInfoDo.getSex())
                .roles(authContext.getRoles())
                .permissions(authContext.getPermissions())
                .accessToken(accessToken)
                .build();
    }
}
